#ifndef MACROS_H
#define MACROS_H

#include <sstream>
#include <iostream>
#include <stdexcept>

#define SQLITE_STATUS_CHECK(STATUS, ERRMSG)         \
do                                                  \
  {                                                 \
  if (STATUS != SQLITE_OK &&                        \
      STATUS != SQLITE_ROW &&                       \
      STATUS != SQLITE_DONE)                        \
    {                                               \
    std::ostringstream err;                         \
    err << ERRMSG << sqlite3_errmsg (m_db) << ends; \
    sqlite3_close (m_db);                           \
    DEBUG_ERR (err.str ());                         \
    throw std::runtime_error (err.str ());          \
    }                                               \
  } while (false);

#define WRITE_STRING(STD_STRING,MSG)      \
  do                                      \
    {                                     \
    std::ostringstream oss;               \
    oss << MSG;                           \
    STD_STRING += oss.str ();             \
    } while (false);

#define WRITE_RESULT_STRING(RESULT, MSG)                          \
  do                                                              \
    {                                                             \
    std::ostringstream msg;                                       \
    msg << MSG << ends;                                           \
                                                                  \
    RESULT.statusMsg.statusMsg_val = (char*) realloc (            \
      RESULT.statusMsg.statusMsg_val,                             \
      sizeof (char) * msg.str ().size ());                        \
    strcpy (RESULT.statusMsg.statusMsg_val, msg.str ().c_str ()); \
                                                                  \
    RESULT.statusMsg.statusMsg_len = msg.str ().size ();          \
    } while (false);

#define DEBUG_X(MSG,TAG)                                      \
  do                                                          \
    {                                                         \
    std::ostringstream msg;                                   \
    msg << MSG << std::endl;                                  \
    std::cout << TAG << " " << __FILE__ << ":" << __LINE__    \
      << " " << msg.str ();                                   \
    } while (false);

#ifndef _NO_DEBUG_LOG
#define DEBUG_LOG(MSG) DEBUG_X(MSG,"[LOG]")
#else
#define DEBUG_LOG(MSG)
#endif

#ifndef _NO_DEBUG_WRN
#define DEBUG_WRN(MSG) DEBUG_X(MSG,"[WRN]")
#else
#define DEBUG_WRN(MSG)
#endif

#ifndef _NO_DEBUG_ERR
#define DEBUG_ERR(MSG) DEBUG_X(MSG,"[ERR]")
#else
#define DEBUG_ERR(MSG)
#endif

#define CHECK_STREAM_ERROR(STREAM,ERRMSG) \
  do                                      \
    {                                     \
    if (!STREAM)                          \
      {                                   \
      ostringstream errss;                \
      errss                               \
        << __FILE__ << ":"                \
        << __LINE__ << " - "              \
        << ERRMSG;                        \
      runtime_error e (errss.str ());     \
      DEBUG_ERR (e.what ());              \
      throw e;                            \
      }                                   \
    } while (false);

#endif /* ifndef MACROS_H */
